package com.yunchao.library.socket.model.response

import com.yunchao.library.socket.extensions.hexString
import com.yunchao.library.socket.utils.BufferPool
import java.nio.ByteBuffer

sealed class BaseResponse(open val error: String = "") {
    open fun toByteArray(): ByteArray {
        val errorBytes = error.encodeToByteArray()
        return BufferPool.use(4 + errorBytes.size) { buffer ->
            buffer.putInt(errorBytes.size)
            buffer.put(errorBytes)
            buffer.array().copyOf(buffer.position())
        }
    }

    companion object {
        // 通用反序列化扩展（供子类复用）
        fun ByteBuffer.readLengthPrefixedString(): String {
            val length = this.int
            return if (length > 0) {
                ByteArray(length).also { get(it) }.decodeToString()
            } else ""
        }

        fun ByteBuffer.readLengthPrefixedBytes(): ByteArray {
            return ByteArray(this.int).also { get(it) }
        }
    }
}

// 各种响应类实现
data class DispatchResponse(override val error: String = "") : BaseResponse()
data class ExecuteResponse(override val error: String = "") : BaseResponse()
data class ConfirmResponse(override val error: String = "") : BaseResponse()
data class MetadataSyncResponse(override val error: String = "") : BaseResponse()
data class SubmitResponse(override val error: String = "") : BaseResponse()
data class AuthorizationResponse(override val error: String = "") : BaseResponse()
data class EnvironmentCheckResponse(override val error: String = "") : BaseResponse()
data class AccessResponse(override val error: String = "") : BaseResponse()


data class DataExchangeResponse(override val error: String = "", val rApdu: ByteArray) :
    BaseResponse() {
        
    companion object {
        /**
         * 创建成功响应
         * @param rApdu 安全令牌返回的应答APDU
         */
        fun success(rApdu: ByteArray): DataExchangeResponse {
            return DataExchangeResponse("", rApdu)
        }

        /**
         * 创建失败响应
         * @param errorMessage 错误描述（非空）
         */
        fun failure(errorMessage: String): DataExchangeResponse {
            require(errorMessage.isNotBlank()) { "Error message cannot be empty" }
            return DataExchangeResponse(errorMessage, byteArrayOf())
        }

        /**
         * 从字节数组解析
         * 格式: [error:L4-V][rApdu:L4-V]
         */
        fun fromByteArray(bytes: ByteArray): DataExchangeResponse {
            return BufferPool.use(bytes.size) { buffer ->
                buffer.put(bytes).flip()
                DataExchangeResponse(
                    error = buffer.readLengthPrefixedString(),
                    rApdu = buffer.readLengthPrefixedBytes()
                )
            }
        }
        /*fun fromByteArray(bytes: ByteArray): DataExchangeResponse {
            val buffer = bytes.toReadOnlyBuffer()

            // 读取error (L4-V)
            val errorLength = buffer.int
            val error = if (errorLength > 0) {
                ByteArray(errorLength).apply { buffer.get(this) }.toString(Charsets.UTF_8)
            } else ""

            // 读取rApdu (L4-V)
            val rApduLength = buffer.int
            val rApdu = ByteArray(rApduLength).apply { buffer.get(this) }

            return DataExchangeResponse(error, rApdu)
        }*/
    }


    /**
    * 转换为字节数组
    * 格式: [error:L4-V][rApdu:L4-V]
    */
    override fun toByteArray(): ByteArray {
        val errorBytes = error.toByteArray(Charsets.UTF_8)
        return BufferPool.use(8 + errorBytes.size + rApdu.size) { buffer ->
            buffer.putInt(errorBytes.size)
                .put(errorBytes)
                .putInt(rApdu.size)
                .put(rApdu)
            buffer.array().copyOf(buffer.position())
        }
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as DataExchangeResponse

        if (error != other.error) return false
        if (!rApdu.contentEquals(other.rApdu)) return false

        return true
    }

    override fun hashCode(): Int {
        var result = error.hashCode()
        result = 31 * result + rApdu.contentHashCode()
        return result
    }

    override fun toString(): String {
        return when {
            error.isEmpty() -> "Success(R-APDU=${rApdu.hexString})"
            else -> "Failure(error='$error')"
        }
    }
}